/*
[栈内存]
全局作用域:window
私有作用域：函数执行
块级作用域：使用let创建变量，存在块级作用域中



[作用域链]
当前作用域代码执行的时候遇到一个变量，我们首先看一下它是否属于私有变量，如果是当前作用域私有变量，那么以后在私有作用域中再遇到这个变量都是操作私有的(“闭包：私有作用域保护私有变量不受外界干扰”)；如果不是私有的变量，向其上级作用域查找，如果也不是上级作用域私有的，就会继续向上查找，直到找到window全局作用域，我们把这种向上一级级查找的机制叫做作用域链;全局下有，操作的就是全局变量，全局下没有（设置：给全局对象window增加了属性名&&获取：报错）

详细过程（背景）↓

函数执行形成一个私有的作用域（保护私有变量），进入到私有作用域中，首先变量提升（声明过的变量是私有的），接下来代码执行

1. 执行的时候遇到一个变量，如果这个变量是私有的，变量不受外界干扰
2. 如果当前这个变量不是私有的，我们需要向它的上级作用域进行查找，上级也没有，则继续向上查找，直到找到window全局作用域为止,我们把这种查找机制叫做[作用域链]
    1)如果上级作用域有，我们当前操作的都是上级作用域中的变量（假如我们在当前作用域把值改了，相当于把上级作用域中的这个值给改了）

    2）如果上级作用域中没有这个变量（找到window也没有）
    如果是设置 → 变量 = 值：相当于给window设置了一个属性，以后再操作window下就有了
    如果是获取 → alert/console(变量)：想要输出这个变量，但此时是没有的，所以会报错

*/

//case:1
/*function fn(){
    a = 123; // <=>window.a = 123;
    console.log(a); //=>123
}
fn();
console.log(a); //=>123*/

//--- --- --- --- ---

//case:2
/*
console.log(x,y);//undefined undefined

//var x=10;var y=20; ↓等同于
var x = 10,
    y = 20;

function fn(){
    console.log(x,y); //undefined 20
    //var x = 100;y=100; ↓等同于
    var x = y = 100;
    console.log(x,y);// 100 100
}

fn();
console.log(x,y);//10,100
*/


/*
查找私有变量

JS中的私有变量有且只有两种:
1. 在私有作用域变量提升阶段声明过的变量或则函数
2. 形参也是私有变量
*/

//私有的有:total、num1、num2
//全局的:result、fn

// function fn(num1,num2){
//     var total = num1 + num2;
//     return total;
// }
//
// var result = fn(100, 200);



/*
函数执行形成一个全新独立的私有的作用域
1、 形参赋值
2、 变量提升
3、 代码自上而下执行
4、 当前栈内存（私有作用域）销毁或则不销毁

注意： 形参赋值在变量提升之前
*/

/*var x=10
    ,y = 20
    ,z = 30;

function fn(x,y){
    //=>[私有作用域]
    //=>形参赋值：x=10 y=20 (x/y都是私有变量) 相当于 var x = 10; var y = 10;
    //=>变量提升:var x(重名时，变量提升也只会执行一次，又因为预解释时变量只会提升不会重新定义，故var x会被忽略)
    console.log(x,y,z); //10 20 30;  =>z不是私有变量，是全局变量
    var x = 100; // =>重名的变量会重新定义  =>私有的x=100
    y = 200; // =>私有的y=200
    z = 300; // =>全局的z=300
    console.log(x,y,z); // 100 200 300
}
fn(x,y,z); // =>fn执行传的的是实参（实参都是值(形参都是变量)，不是值要转换成值，这里传递的不是变量，而是变量的值传过去了）
console.log(x,y,z); //=>10 20 300*/



//=>[私有作用域]
//=>形参赋值:b=1 (私有变量)
//=>变量提升:b=aaafff111(此处赋值操作替换了形参赋值的内容)
function fn(b){
    console.log(b); // [Function: b] =>函数b本身
    function b(){
        //=>[私有作用域]
        //=>形参赋值和变量提升都没有
        console.log(b);
    }
    b(); // [Function: b] =>函数b本身
}
fn(1);
